#pragma once
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "log.hpp"
string defaultip = "0.0.0.0";
Log lg;

class Server
{
public:
    Server()
    {}

    Server(uint16_t& port)
    :port_(port), ip_(defaultip)
    {}

    //启动服务器
    void Run()
    {
        //创建套接字
        int sockfd = socket(AF_INET, SOCK_DGRAM, 0);//UDP
        if(sockfd < 0)
        {
            lg(Fatal, "无法创建套接字: %s, errno: %d", strerror(errno), errno);
            exit(1);
        }

        //绑定端口号(先准备好对应的报文结构体数据，用于接收报文)
        //准备数据
        struct sockaddr_in addr;
        bzero(&addr, sizeof(addr));//将结构体里的内容全部置为0
        addr.sin_zero;//填充段，不处理
        addr.sin_port = htons(port_);//端口号转为网络序列
        //addr.sin_addr.s_addr = inet_addr(ip_.c_str());// inet_addr将char*类型转为uint32_t类型，而ip_是一种0.0.0.0的string字符串，需要c_str()
        addr.sin_addr.s_addr = htonl(INADDR_ANY);

        //绑定端口号
        socklen_t len = sizeof(sockaddr_in);//用上面创建的报文，给进程绑定端口号
        bind(sockfd, (const sockaddr*)&addr, len);
        lg(Info,"成功绑定端口号");

        cout << "Server config: " << "ip: " << addr.sin_addr.s_addr << " port: " << addr.sin_port << endl;

        lg.enable(Print);
        lg(Info,"成功开启服务器");

        while(true)
        {
            //接收数据
            struct sockaddr_in receive;
            socklen_t relen = sizeof(receive);
            bzero(&receive, sizeof(receive));//将结构体里的内容全部置为0
            char buffer[1024];
            lg(Info,"等待数据ing...");
            ssize_t result = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&receive, &relen);//返回的是读取到的字节,阻塞等待
            lg(Info,"接收到了%d个数据", result);
            if(result < 0)
            {
                lg(Warning, "接收数据失败: %s,errno: %d", strerror(errno), errno);
                continue;
            }
            buffer[result] = 0;

            //处理数据
            cout << "Server read: " << buffer << endl;
        }

    }
    ~Server()
        {}
private:
    uint16_t port_;
    string ip_;

};